 package client.anticheat;

 import client.MapleCharacter;
 import client.MapleCharacterUtil;
 import client.skills.SkillFactory;
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import constants.SkillConstants;
 import handling.world.WorldBroadcastService;
 import handling.world.WorldFindService;
 import java.awt.Point;
 import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.EnumMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import server.AutobanManager;
 import server.Timer;
 import tools.MaplePacketCreator;
 import tools.StringUtil;

 @JsonIgnoreProperties({"lock", "rL", "wL"})
 public class CheatTracker {
/*  30 */   private static final Logger log = LogManager.getLogger(CheatTracker.class);
/*  31 */   private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
/*  32 */   private final Lock rL = this.lock.readLock();
/*  33 */   private final Lock wL = this.lock.writeLock();
/*  34 */   private final Map<CheatingOffense, CheatingOffenseEntry> offenses = new EnumMap<>(CheatingOffense.class);

   private Integer ownerid;
/*  37 */   private long lastAttackTime = 0L;
/*  38 */   private int lastAttackTickCount = 0;
/*  39 */   private byte Attack_tickResetCount = 0;
/*  40 */   private long Server_ClientAtkTickDiff = 0L;
/*  41 */   private long lastDamage = 0L;
   private long takingDamageSince;
/*  43 */   private int numSequentialDamage = 0;
/*  44 */   private long lastDamageTakenTime = 0L;
/*  45 */   private byte numZeroDamageTaken = 0;
/*  46 */   private int numSameDamage = 0;
   private Point lastMonsterMove;
   private int monsterMoveCount;
/*  49 */   private int attacksWithoutHit = 0;
/*  50 */   private byte dropsPerSecond = 0;
/*  51 */   private long lastDropTime = 0L;
/*  52 */   private byte msgsPerSecond = 0;
/*  53 */   private long lastMsgTime = 0L;
   private ScheduledFuture<?> invalidationTask;
/*  55 */   private int gm_message = 0;
/*  56 */   private int lastTickCount = 0; private int tickSame = 0; private int inMapIimeCount = 0; private int lastPickupkCount = 0;
/*  57 */   private long lastSmegaTime = 0L; private long lastBBSTime = 0L; private long lastASmegaTime = 0L; private long lastMZDTime = 0L; private long lastCraftTime = 0L; private long lastSaveTime = 0L; private long lastLieDetectorTime = 0L; private long lastPickupkTime = 0L; private long lastFinalAttack = 0L;

   private long lastlogonTime;

/*  61 */   private int numSequentialFamiliarAttack = 0;
/*  62 */   private long familiarSummonTime = 0L;

   private AtomicInteger lastForceAtom;

   private int lastFinalAttackTime;


   public CheatTracker(Integer ownerid) {
/*  70 */     start(ownerid);
   }

   private MapleCharacter getPlayer() {
/*  74 */     return WorldFindService.getInstance().findCharacterById(this.ownerid.intValue());
   }




   public void checkAttack(int skillId, int tickcount) {
/*  81 */     int AtkDelay = SkillConstants.getAttackDelay(skillId, (skillId == 0) ? null : SkillFactory.getSkill(skillId));
/*  82 */     if (tickcount - this.lastAttackTickCount < AtkDelay);






/*  89 */     this.lastAttackTime = System.currentTimeMillis();
/*  90 */     MapleCharacter player = getPlayer();
/*  91 */     if (player != null && this.lastAttackTime - player.getChangeTime() > 600000L) {
/*  92 */       player.setChangeTime(false);

/*  94 */       if (!player.isInTownMap() && player.getEventInstance() == null && player.getMap().getMobsSize() >= 2) {
/*  95 */         this.inMapIimeCount++;
/*  96 */         if (this.inMapIimeCount >= 6) {
/*  97 */           WorldBroadcastService.getInstance().broadcastGMMessage(MaplePacketCreator.serverNotice(6, "[GM消息] " + player.getName() + " ID: " + player.getId() + " (等级 " + player.getLevel() + ") 在地图: " + player.getMapId() + " 打怪时间超过1小时，该玩家可能是在挂机打怪。"));
         }
/*  99 */         if (this.inMapIimeCount >= 8) {
/* 100 */           this.inMapIimeCount = 0;
         }
       }
     }




/* 108 */     long STime_TC = this.lastAttackTime - tickcount;
/* 109 */     if (this.Server_ClientAtkTickDiff - STime_TC > 1000L && 
/* 110 */       player != null && player.isAdmin()) {
/* 111 */       player.dropMessage(-5, "攻击速度异常2 技能: " + skillId + " 当前: " + (this.Server_ClientAtkTickDiff - STime_TC));
     }






/* 119 */     this.Attack_tickResetCount = (byte)(this.Attack_tickResetCount + 1);
/* 120 */     if (this.Attack_tickResetCount >= ((AtkDelay <= 200) ? 1 : 4)) {
/* 121 */       this.Attack_tickResetCount = 0;
/* 122 */       this.Server_ClientAtkTickDiff = STime_TC;
     }
/* 124 */     updateTick(tickcount);
/* 125 */     this.lastAttackTickCount = tickcount;
   }




   public void resetInMapIimeCount() {
/* 132 */     this.inMapIimeCount = 0;
   }




   public void checkPVPAttack(int skillId) {
/* 139 */     int AtkDelay = SkillConstants.getAttackDelay(skillId, (skillId == 0) ? null : SkillFactory.getSkill(skillId));
/* 140 */     long STime_TC = System.currentTimeMillis() - this.lastAttackTime;
/* 141 */     if (STime_TC < AtkDelay) {
/* 142 */       registerOffense(CheatingOffense.FASTATTACK, "攻击速度异常.");
     }
/* 144 */     this.lastAttackTime = System.currentTimeMillis();
   }

   public long getLastAttack() {
/* 148 */     return this.lastAttackTime;
   }




   public void checkTakeDamage(int damage) {
/* 155 */     this.numSequentialDamage++;
/* 156 */     this.lastDamageTakenTime = System.currentTimeMillis();





/* 162 */     if (this.lastDamageTakenTime - this.takingDamageSince / 500L < this.numSequentialDamage) {
/* 163 */       registerOffense(CheatingOffense.FAST_TAKE_DAMAGE, "掉血次数异常.");
     }
/* 165 */     if (this.lastDamageTakenTime - this.takingDamageSince > 4500L) {
/* 166 */       this.takingDamageSince = this.lastDamageTakenTime;
/* 167 */       this.numSequentialDamage = 0;
     }



/* 172 */     if (damage == 0) {
/* 173 */       this.numZeroDamageTaken = (byte)(this.numZeroDamageTaken + 1);
/* 174 */       if (this.numZeroDamageTaken >= 50) {
/* 175 */         this.numZeroDamageTaken = 0;
/* 176 */         registerOffense(CheatingOffense.HIGH_AVOID, "回避率过高.");
       }
/* 178 */     } else if (damage != -1) {
/* 179 */       this.numZeroDamageTaken = 0;
     }
   }




   public void resetTakeDamage() {
/* 187 */     this.numZeroDamageTaken = 0;
   }




   public void checkSameDamage(long dmg, double expected) {
/* 194 */     MapleCharacter player = getPlayer();
/* 195 */     if (dmg > 2000L && this.lastDamage == dmg && player != null && (player.getLevel() < 190 || dmg > expected * 2.0D)) {
/* 196 */       this.numSameDamage++;
/* 197 */       if (this.numSameDamage > 5) {
/* 198 */         registerOffense(CheatingOffense.SAME_DAMAGE, this.numSameDamage + " times, 攻击伤害 " + dmg + ", 预期伤害 " + expected + " [等级: " + player.getLevel() + ", 职业: " + player.getJob() + "]");
/* 199 */         this.numSameDamage = 0;
       }
     } else {
/* 202 */       this.lastDamage = dmg;
/* 203 */       this.numSameDamage = 0;
     }
   }




   public void checkHighDamage(int eachd, double maxDamagePerHit, int mobId, int skillId) {
/* 211 */     MapleCharacter player = getPlayer();
/* 212 */     if (eachd > maxDamagePerHit && maxDamagePerHit > 2000.0D && player != null) {
/* 213 */       registerOffense(CheatingOffense.HIGH_DAMAGE, "[伤害: " + eachd + ", 预计伤害: " + maxDamagePerHit + ", 怪物ID: " + mobId + "] [职业: " + player.getJob() + ", 等级: " + player.getLevel() + ", 技能: " + skillId + "]");
/* 214 */       if (eachd > maxDamagePerHit * 2.0D) {
/* 215 */         registerOffense(CheatingOffense.HIGH_DAMAGE_2, "[伤害: " + eachd + ", 预计伤害: " + maxDamagePerHit + ", 怪物ID: " + mobId + "] [职业: " + player.getJob() + ", 等级: " + player.getLevel() + ", 技能: " + skillId + "]");
       }
     }
   }




   public void checkMoveMonster(Point pos) {
/* 224 */     if (pos.equals(this.lastMonsterMove)) {
/* 225 */       this.monsterMoveCount++;
/* 226 */       if (this.monsterMoveCount > 10) {
/* 227 */         registerOffense(CheatingOffense.MOVE_MONSTERS, "吸怪 坐标: " + pos.x + ", " + pos.y);
/* 228 */         this.monsterMoveCount = 0;
       }
     } else {
/* 231 */       this.lastMonsterMove = pos;
/* 232 */       this.monsterMoveCount = 1;
     }
   }

   public void resetFamiliarAttack() {
/* 237 */     this.familiarSummonTime = System.currentTimeMillis();
/* 238 */     this.numSequentialFamiliarAttack = 0;
   }
















   public boolean checkFamiliarAttack(MapleCharacter chr) {
/* 257 */     this.numSequentialFamiliarAttack++;


/* 260 */     if ((System.currentTimeMillis() - this.familiarSummonTime) / 601L < this.numSequentialFamiliarAttack) {
/* 261 */       registerOffense(CheatingOffense.FAST_SUMMON_ATTACK, "召唤兽攻击速度异常.");
/* 262 */       return false;
     }
/* 264 */     return true;
   }




   public void checkPickup(int count, boolean pet) {
/* 271 */     if (System.currentTimeMillis() - this.lastPickupkTime < 1000L) {
/* 272 */       this.lastPickupkCount++;
/* 273 */       MapleCharacter player = getPlayer();
/* 274 */       if (this.lastPickupkCount >= count && player != null && !player.isGM()) {
/* 275 */         log.info("[作弊] " + player.getName() + " (等级 " + player.getLevel() + ") " + (pet ? "宠物" : "角色") + "捡取 checkPickup 次数: " + this.lastPickupkCount + " 服务器断开他的连接。");
/* 276 */         player.getClient().disconnect(true, false);
/* 277 */         if (player.getClient() != null && player.getClient().getSession().isActive()) {
/* 278 */           player.getClient().getSession().close();
         }
       }
     } else {
/* 282 */       this.lastPickupkCount = 0;
     }
/* 284 */     this.lastPickupkTime = System.currentTimeMillis();
   }




   public void checkDrop() {
/* 291 */     checkDrop(false);
   }




   public void checkDrop(boolean dc) {
/* 298 */     if (System.currentTimeMillis() - this.lastDropTime < 1000L) {
/* 299 */       this.dropsPerSecond = (byte)(this.dropsPerSecond + 1);
/* 300 */       MapleCharacter player = getPlayer();
/* 301 */       if (this.dropsPerSecond >= (dc ? 32 : 16) && player != null && !player.isGM()) {
/* 302 */         if (dc) {
/* 303 */           player.getClient().disconnect(true, false);
/* 304 */           if (player.getClient().getSession().isActive()) {
/* 305 */             player.getClient().getSession().close();
           }
/* 307 */           log.info("[作弊] " + player.getName() + " (等级 " + player.getLevel() + ") checkDrop 次数: " + this.dropsPerSecond + " 服务器断开他的连接。");
         } else {
/* 309 */           player.getClient().setMonitored(true);
         }
       }
     } else {
/* 313 */       this.dropsPerSecond = 0;
     }
/* 315 */     this.lastDropTime = System.currentTimeMillis();
   }




   public void checkMsg() {
/* 322 */     if (System.currentTimeMillis() - this.lastMsgTime < 1000L) {
/* 323 */       this.msgsPerSecond = (byte)(this.msgsPerSecond + 1);
/* 324 */       MapleCharacter player = getPlayer();
/* 325 */       if (this.msgsPerSecond > 10 && player != null && !player.isGM()) {
/* 326 */         player.getClient().disconnect(true, false);
/* 327 */         if (player.getClient().getSession().isActive()) {
/* 328 */           player.getClient().getSession().close();
         }
/* 330 */         log.info("[作弊] " + player.getName() + " (等级 " + player.getLevel() + ") checkMsg 次数: " + this.msgsPerSecond + " 服务器断开他的连接。");
       }
     } else {
/* 333 */       this.msgsPerSecond = 0;
     }
/* 335 */     this.lastMsgTime = System.currentTimeMillis();
   }

   public int getAttacksWithoutHit() {
/* 339 */     return this.attacksWithoutHit;
   }

   public void setAttacksWithoutHit(boolean increase) {
/* 343 */     if (increase) {
/* 344 */       this.attacksWithoutHit++;
     } else {
/* 346 */       this.attacksWithoutHit = 0;
     }
   }

   public void registerOffense(CheatingOffense offense) {
/* 351 */     registerOffense(offense, null);
   }

   public void registerOffense(CheatingOffense offense, String param) {
/* 355 */     MapleCharacter chrhardref = getPlayer();
/* 356 */     if (chrhardref == null || !offense.isEnabled() || chrhardref.isGM()) {
       return;
     }
/* 359 */     CheatingOffenseEntry entry = null;
/* 360 */     this.rL.lock();
     try {
/* 362 */       entry = this.offenses.get(offense);
     } finally {
/* 364 */       this.rL.unlock();
     }
/* 366 */     if (entry != null && entry.isExpired()) {
/* 367 */       expireEntry(entry);
/* 368 */       entry = null;
/* 369 */       this.gm_message = 0;
     }
/* 371 */     if (entry == null) {
/* 372 */       entry = new CheatingOffenseEntry(offense, chrhardref.getId());
     }
/* 374 */     if (param != null) {
/* 375 */       entry.setParam(param);
     }
/* 377 */     entry.incrementCount();
/* 378 */     if (offense.shouldAutoban(entry.getCount())) {
/* 379 */       byte type = offense.getBanType();
/* 380 */       if (type == 1) {
/* 381 */         AutobanManager.getInstance().autoban(chrhardref.getClient(), StringUtil.makeEnumHumanReadable(offense.name()));
/* 382 */       } else if (type == 2) {
/* 383 */         chrhardref.getClient().disconnect(true, false);
/* 384 */         if (chrhardref.getClient().getSession().isActive()) {
/* 385 */           chrhardref.getClient().getSession().close();
         }
/* 387 */         log.info("[作弊] " + chrhardref.getName() + " (等级:" + chrhardref.getLevel() + " 职业:" + chrhardref.getJob() + ") 服务器断开他的连接. 原因: " + StringUtil.makeEnumHumanReadable(offense.name()) + ((param == null) ? "" : (" - " + param)));
       }
/* 389 */       this.gm_message = 0;
       return;
     }
/* 392 */     this.wL.lock();
     try {
/* 394 */       this.offenses.put(offense, entry);
     } finally {
/* 396 */       this.wL.unlock();
     }
/* 398 */     switch (offense) {






       case SAME_DAMAGE:
/* 406 */         this.gm_message++;
/* 407 */         if (this.gm_message % 100 == 0) {
/* 408 */           log.info("[作弊] " + MapleCharacterUtil.makeMapleReadable(chrhardref.getName()) + " ID: " + chrhardref.getId() + " (等级 " + chrhardref.getLevel() + ") 使用非法程序! " + StringUtil.makeEnumHumanReadable(offense.name()) + ((param == null) ? "" : (" - " + param)));
/* 409 */           WorldBroadcastService.getInstance().broadcastGMMessage(MaplePacketCreator.serverNotice(6, "[GM消息] " + MapleCharacterUtil.makeMapleReadable(chrhardref.getName()) + " ID: " + chrhardref.getId() + " (等级 " + chrhardref.getLevel() + ") 使用非法程序! " + StringUtil.makeEnumHumanReadable(offense.name()) + ((param == null) ? "" : (" - " + param))));
         }
/* 411 */         if (this.gm_message >= 20 && chrhardref.getLevel() < ((offense == CheatingOffense.SAME_DAMAGE) ? 180 : 190)) {
/* 412 */           Timestamp chrCreated = chrhardref.getChrCreated();
/* 413 */           long time = System.currentTimeMillis();
/* 414 */           if (chrCreated != null) {
/* 415 */             time = chrCreated.getTime();
           }
/* 417 */           if (time + 1296000000L >= System.currentTimeMillis()) {
/* 418 */             AutobanManager.getInstance().autoban(chrhardref.getClient(), StringUtil.makeEnumHumanReadable(offense.name()) + " over 500 times " + ((param == null) ? "" : (" - " + param))); break;
           }
/* 420 */           this.gm_message = 0;
/* 421 */           WorldBroadcastService.getInstance().broadcastGMMessage(MaplePacketCreator.serverNotice(6, "[GM消息] " + MapleCharacterUtil.makeMapleReadable(chrhardref.getName()) + " ID: " + chrhardref.getId() + " (等级 " + chrhardref.getLevel() + ") 使用非法程序! " + StringUtil.makeEnumHumanReadable(offense.name()) + ((param == null) ? "" : (" - " + param))));
/* 422 */           log.info("[GM消息] " + MapleCharacterUtil.makeMapleReadable(chrhardref.getName()) + " ID: " + chrhardref.getId() + " (等级 " + chrhardref.getLevel() + ") 使用非法程序! " + StringUtil.makeEnumHumanReadable(offense.name()) + ((param == null) ? "" : (" - " + param)));
         }
         break;
     }

/* 427 */     CheatingOffensePersister.getInstance().persistEntry(entry);
   }

   public void updateTick(int newTick) {
/* 431 */     if (newTick <= this.lastTickCount) {
/* 432 */       MapleCharacter player = getPlayer();
/* 433 */       if (this.tickSame >= 30 && player != null && !player.isGM()) {
/* 434 */         player.getClient().disconnect(true, false);
/* 435 */         if (player.getClient().getSession().isActive()) {
/* 436 */           player.getClient().getSession().close();
         }
/* 438 */         log.info("[作弊] " + player.getName() + " (等级 " + player.getLevel() + ") updateTick 次数: " + this.tickSame + " 服务器断开他的连接。");
       } else {
/* 440 */         this.tickSame++;
       }
     } else {
/* 443 */       this.tickSame = 0;
     }
/* 445 */     this.lastTickCount = newTick;
   }




   public boolean canSmega() {
/* 452 */     MapleCharacter player = getPlayer();
/* 453 */     if (this.lastSmegaTime > System.currentTimeMillis() && player != null && !player.isGM()) {
/* 454 */       return false;
     }
/* 456 */     this.lastSmegaTime = System.currentTimeMillis();
/* 457 */     return true;
   }




   public boolean canAvatarSmega() {
/* 464 */     MapleCharacter player = getPlayer();
/* 465 */     if (this.lastASmegaTime > System.currentTimeMillis() && player != null && !player.isGM()) {
/* 466 */       return false;
     }
/* 468 */     this.lastASmegaTime = System.currentTimeMillis();
/* 469 */     return true;
   }




   public boolean canBBS() {
/* 476 */     MapleCharacter player = getPlayer();
/* 477 */     if (this.lastBBSTime + 60000L > System.currentTimeMillis() && player != null && !player.isGM()) {
/* 478 */       return false;
     }
/* 480 */     this.lastBBSTime = System.currentTimeMillis();
/* 481 */     return true;
   }




   public boolean canMZD() {
/* 488 */     MapleCharacter player = getPlayer();
/* 489 */     if (this.lastMZDTime > System.currentTimeMillis() && player != null && !player.isGM()) {
/* 490 */       return false;
     }
/* 492 */     this.lastMZDTime = System.currentTimeMillis();
/* 493 */     return true;
   }




   public boolean canCraftMake() {
/* 500 */     MapleCharacter player = getPlayer();
/* 501 */     if (this.lastCraftTime + 3000L > System.currentTimeMillis() && player != null && !player.isGM()) {
/* 502 */       return false;
     }
/* 504 */     this.lastCraftTime = System.currentTimeMillis();
/* 505 */     return true;
   }




   public boolean canSaveDB() {
/* 512 */     if (this.lastSaveTime + 180000L > System.currentTimeMillis() && getPlayer() != null) {
/* 513 */       return false;
     }
/* 515 */     this.lastSaveTime = System.currentTimeMillis();
/* 516 */     return true;
   }

   public int getlastSaveTime() {
/* 520 */     if (this.lastSaveTime <= 0L) {
/* 521 */       this.lastSaveTime = System.currentTimeMillis();
     }
/* 523 */     return (int)((this.lastSaveTime + 180000L - System.currentTimeMillis()) / 1000L);
   }




   public boolean canLieDetector() {
/* 530 */     if (this.lastLieDetectorTime + 300000L > System.currentTimeMillis() && getPlayer() != null) {
/* 531 */       return false;
     }
/* 533 */     this.lastLieDetectorTime = System.currentTimeMillis();
/* 534 */     return true;
   }




   public long getLastlogonTime() {
/* 541 */     if (this.lastlogonTime <= 0L || getPlayer() == null) {
/* 542 */       this.lastlogonTime = System.currentTimeMillis();
     }
/* 544 */     return this.lastlogonTime;
   }

   public void expireEntry(CheatingOffenseEntry coe) {
/* 548 */     this.wL.lock();
     try {
/* 550 */       this.offenses.remove(coe.getOffense());
     } finally {
/* 552 */       this.wL.unlock();
     }
   }
   public int getPoints() {
     CheatingOffenseEntry[] offenses_copy;
/* 557 */     int ret = 0;

/* 559 */     this.rL.lock();
     try {
/* 561 */       offenses_copy = (CheatingOffenseEntry[])this.offenses.values().toArray((Object[])new CheatingOffenseEntry[this.offenses.size()]);
     } finally {
/* 563 */       this.rL.unlock();
     }
/* 565 */     for (CheatingOffenseEntry entry : offenses_copy) {
/* 566 */       if (entry.isExpired()) {
/* 567 */         expireEntry(entry);
       } else {
/* 569 */         ret += entry.getPoints();
       }
     }
/* 572 */     return ret;
   }

   public Map<CheatingOffense, CheatingOffenseEntry> getOffenses() {
/* 576 */     return Collections.unmodifiableMap(this.offenses);
   }

   public String getSummary() {
/* 580 */     StringBuilder ret = new StringBuilder();
/* 581 */     List<CheatingOffenseEntry> offenseList = new ArrayList<>();
/* 582 */     this.rL.lock();
     try {
/* 584 */       for (CheatingOffenseEntry entry : this.offenses.values()) {
/* 585 */         if (!entry.isExpired()) {
/* 586 */           offenseList.add(entry);
         }
       }
     } finally {
/* 590 */       this.rL.unlock();
     }
/* 592 */     offenseList.sort((o1, o2) -> {
           int thisVal = o1.getPoints();
           int anotherVal = o2.getPoints();
           return (thisVal < anotherVal) ? 1 : ((thisVal == anotherVal) ? 0 : -1);
         });
/* 597 */     int to = Math.min(offenseList.size(), 4);
/* 598 */     for (int x = 0; x < to; x++) {
/* 599 */       ret.append(StringUtil.makeEnumHumanReadable(((CheatingOffenseEntry)offenseList.get(x)).getOffense().name()));
/* 600 */       ret.append(": ");
/* 601 */       ret.append(((CheatingOffenseEntry)offenseList.get(x)).getCount());
/* 602 */       if (x != to - 1) {
/* 603 */         ret.append(" ");
       }
     }
/* 606 */     return ret.toString();
   }

   public void dispose() {
/* 610 */     if (this.invalidationTask != null) {
/* 611 */       this.invalidationTask.cancel(false);
     }
/* 613 */     this.invalidationTask = null;
   }

   public final void start(Integer ownerid) {
/* 617 */     this.ownerid = ownerid;
/* 618 */     this.invalidationTask = Timer.CheatTimer.getInstance().register(new InvalidationTask(), 60000L);
/* 619 */     this.takingDamageSince = System.currentTimeMillis();
/* 620 */     this.lastForceAtom = new AtomicInteger(1);
   }

   private class InvalidationTask implements Runnable {
     private InvalidationTask() {}

     public void run() {
       CheatingOffenseEntry[] offenses_copy;
/* 628 */       CheatTracker.this.rL.lock();
       try {
/* 630 */         offenses_copy = (CheatingOffenseEntry[])CheatTracker.this.offenses.values().toArray((Object[])new CheatingOffenseEntry[CheatTracker.this.offenses.size()]);
       } finally {
/* 632 */         CheatTracker.this.rL.unlock();
       }
/* 634 */       for (CheatingOffenseEntry offense : offenses_copy) {
/* 635 */         if (offense.isExpired()) {
/* 636 */           CheatTracker.this.expireEntry(offense);
         }
       }
/* 639 */       if (CheatTracker.this.getPlayer() == null) {
/* 640 */         CheatTracker.this.dispose();
       }
     }
   }

   public void setLastFinalAttack(int tick) {
/* 646 */     this.lastFinalAttackTime = tick;
   }

   public void resetFinalAttack() {
/* 650 */     this.lastFinalAttack = System.currentTimeMillis();
   }

   public int getLastForceAtom() {
/* 654 */     return this.lastForceAtom.getAndIncrement();
   }

   public int checkLastFinalAttack() {
/* 658 */     return (int)(System.currentTimeMillis() - this.lastFinalAttack + this.lastFinalAttackTime);
   }

   public CheatTracker() {}
 }


/* Location:              C:\PGX\Server.jar!\client\anticheat\CheatTracker.class
 * Java compiler version: 8 (52.0)
 * JD-Core Version:       1.1.3
 */